﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
#if UNITY_EDITOR
using Sirenix.OdinInspector;
#endif

namespace Hsenl {
    // 该池针对的是dotnet object
    [Serializable]
    public class ObjectPoolManager<TItem> : Singleton<ObjectPoolManager<TItem>> where TItem : class {
#if UNITY_EDITOR
        [ShowInInspector, ReadOnly]
#endif
        private ConcurrentDictionary<Type, ConcurrentQueue<TItem>> _pool = new();

        public bool Contains<T>() where T : TItem {
            var type = typeof(T);
            if (this._pool.TryGetValue(type, out var queue)) {
                if (!queue.IsEmpty) {
                    return true;
                }
            }

            return false;
        }

        public virtual T Rent<T>() where T : class, TItem {
            return this.Rent(typeof(T)) as T;
        }

        public virtual object Rent(Type type) {
            TItem result = null;
            if (this._pool.TryGetValue(type, out var queue)) {
                queue.TryDequeue(out result);
            }

            result ??= Activator.CreateInstance(type) as TItem;
            return result;
        }

        public virtual void Return(TItem obj) {
            if (obj == null) {
                return;
            }

            var type = obj.GetType();
            if (!this._pool.TryGetValue(type, out var queue)) {
                queue = new ConcurrentQueue<TItem>();
                this._pool.TryAdd(type, queue);
            }

            // 一种对象最大为1000个
            // if (queue.Count > 1000) {
            //     Log.Warning($"object pool return exceeds the upper limit 1000 '{obj}'");
            //     return;
            // }

            queue.Enqueue(obj);
        }

        public void Clear() {
            this._pool.Clear();
        }

        public void Clear<T>() where T : TItem {
            this.Clear(typeof(T));
        }

        public void Clear(Type type) {
            if (this._pool.Remove(type, out var queue)) {
                queue.Clear();
            }
        }

        protected override void OnUnregister() {
            this.Clear();
        }
    }

    [Serializable]
    public class ObjectPoolManager : ObjectPoolManager<object> { }
}